package com.neusoft.neuiotms.dcam.fixed.service.impl;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import javax.persistence.EntityNotFoundException;
import javax.transaction.Transactional;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import com.neusoft.bizcore.web.constant.ExceptionConstants;
import com.neusoft.bizcore.web.dto.result.ResultListDTO;
import com.neusoft.bizcore.web.exception.UnitedException;
import com.neusoft.bizcore.web.support.Searchable;
import com.neusoft.neuiotms.dcam.common.model.Manufacturer;
import com.neusoft.neuiotms.dcam.common.repository.ManufacturerRepository;
import com.neusoft.neuiotms.dcam.common.util.CodeGenerator;
import com.neusoft.neuiotms.dcam.fixed.converter.AssetConverter;
import com.neusoft.neuiotms.dcam.fixed.converter.MaintenanceChangeConverter;
import com.neusoft.neuiotms.dcam.fixed.dto.AssetDTO;
import com.neusoft.neuiotms.dcam.fixed.dto.MaintenanceChangeDTO;
import com.neusoft.neuiotms.dcam.fixed.model.MaintenanceChange;
import com.neusoft.neuiotms.dcam.fixed.model.enums.MaintenanceChangeStatus;
import com.neusoft.neuiotms.dcam.fixed.repository.MaintenanceChangeRepository;
import com.neusoft.neuiotms.dcam.fixed.service.AssetService;
import com.neusoft.neuiotms.dcam.fixed.service.MaintenanceChangeService;
import com.neusoft.neuiotms.micro.auth.AuthMicroService;

import lombok.extern.slf4j.Slf4j;

@Service
@Slf4j
@Transactional
public class MaintenanceChangeServiceImpl implements MaintenanceChangeService {

    @Autowired
    private MaintenanceChangeRepository changeRepository;

    @Autowired
    private MaintenanceChangeConverter changeConverter;

    @Autowired
    private AssetService assetService;

    @Autowired
    private AssetConverter assetConverer;

    @Autowired
    private ManufacturerRepository manfacturerRepository;

    @Autowired
    private AuthMicroService authMicroService;

    @Override
    public MaintenanceChangeDTO create(final MaintenanceChangeDTO dto) {
        dto.setCode(CodeGenerator.maintenanceChangeGenerator());
        final MaintenanceChange model = this.changeConverter.toModel(dto);
        if (dto.getManufacturerId() != null) {
            try {
                final Manufacturer manufacturer = this.manfacturerRepository.getOne(dto.getManufacturerId());
                model.setManufacturer(manufacturer);
            } catch (final EntityNotFoundException e) {
                throw new UnitedException(ExceptionConstants.ENTITY_NOT_FOUND, new Object[] {dto.getManufacturerId() });
            }
        }
        if ((dto.getAssets() != null) && !dto.getAssets().isEmpty()) {
            //            final String[] assetCodes =
            //                    (String[]) dto.getAssets().stream().map(AssetDTO::getCode).collect(Collectors.toList()).toArray();
            final List<String> str = dto.getAssets().stream().map(AssetDTO::getCode).collect(Collectors.toList());
            final String[] assetCodes = str.toArray(new String[1]);
            final Searchable searchable = new Searchable();
            searchable.put("codes", assetCodes);
            final Page<AssetDTO> assets = this.assetService.search(Pageable.unpaged(), searchable);
            if (assets.getTotalElements() > 0) {
                model.setAssets(this.assetConverer.toListModel(assets.getContent()));
            } else {
                throw new UnitedException("至少选择一个资产", new Object[] {});
            }
        }
        this.changeRepository.save(model);
        MaintenanceChangeServiceImpl.log.info("维保变更新增成功 ： " + dto);
        return this.changeConverter.toDTO(model);
    }

    @Override
    public void delete(final Long id) {

        try {
            final MaintenanceChange model = this.changeRepository.getOne(id);
            if (model.getChangeStatus() != MaintenanceChangeStatus.created) {
                MaintenanceChangeServiceImpl.log.info("维保变更已经受理，不允许删除 +id： " + id);
                throw new UnitedException("维保变更已经受理，不允许删除！");
            }
            this.changeRepository.deleteById(id);
            MaintenanceChangeServiceImpl.log.info("维保变更删除成功");
        } catch (final EntityNotFoundException e) {
            throw new UnitedException(ExceptionConstants.ENTITY_NOT_FOUND, new Object[] {id });
        }

    }

    @Override
    public MaintenanceChangeDTO update(final Long id, final MaintenanceChangeDTO dto) {
        MaintenanceChange model;
        try {
            model = this.changeRepository.getOne(id);
            if (model.getChangeStatus() != MaintenanceChangeStatus.created) {
                MaintenanceChangeServiceImpl.log.info("维保变更已经受理，不允许编辑 +id： " + id);
                throw new UnitedException("维保变更已经受理，不允许编辑！");
            }
        } catch (final EntityNotFoundException e) {
            throw new UnitedException(ExceptionConstants.ENTITY_NOT_FOUND, new Object[] {id });
        }

        if (dto.getManufacturerId() != null) {
            try {
                final Manufacturer manufacturer = this.manfacturerRepository.getOne(dto.getManufacturerId());
                model.setManufacturer(manufacturer);
            } catch (final EntityNotFoundException e) {
                throw new UnitedException(ExceptionConstants.ENTITY_NOT_FOUND, new Object[] {dto.getManufacturerId() });
            }
        }
        if ((dto.getAssets() != null) && !dto.getAssets().isEmpty()) {
            final String[] assetCodes =
                    dto.getAssets().stream().map(AssetDTO::getCode).collect(Collectors.toList()).toArray(new String[1]);
            final Searchable searchable = new Searchable();
            searchable.put("codes", assetCodes);
            final Page<AssetDTO> assets = this.assetService.search(Pageable.unpaged(), searchable);
            if (assets.getTotalElements() > 0) {
                model.setAssets(this.assetConverer.toListModel(assets.getContent()));
            } else {
                throw new UnitedException("至少选择一个资产", new Object[] {id });
            }
        }
        dto.setId(model.getId());
        model = this.changeConverter.toModel(dto);
        this.changeRepository.save(model);

        MaintenanceChangeServiceImpl.log.info("维保更新成功 id： " + id);
        final MaintenanceChangeDTO confirmdto = this.changeConverter.toDTO(model);
        if (confirmdto.getChangeStatus().equals(MaintenanceChangeStatus.created.getCode())) {
            return confirmdto;
        } else {
            return this.changeAssetMaintenanceInfo(confirmdto);
        }
    }

    @Override
    public List<MaintenanceChangeDTO> findAll() {
        final List<MaintenanceChange> maintenances = this.changeRepository.findAll();
        final List<MaintenanceChangeDTO> maintenanceDtos = this.changeConverter.toListDTO(maintenances);
        return maintenanceDtos;
    }

    @Override
    public MaintenanceChangeDTO details(final Long id) {
        final MaintenanceChange model;
        try {
            model = this.changeRepository.getOne(id);
        } catch (final EntityNotFoundException e) {
            throw new UnitedException(ExceptionConstants.ENTITY_NOT_FOUND, new Object[] {id });
        }
        return this.changeConverter.toDTO(model, false);
    }

    @Override
    public Page<MaintenanceChangeDTO> search(final Pageable pageable, final Searchable searchable) {
        final Page<MaintenanceChange> models = this.changeRepository.search(pageable, searchable);

        final Page<MaintenanceChangeDTO> resultDTO = this.changeConverter.toPageDTO(models);
        final Map<String, String[]> usernames = new HashMap<>();
        usernames.put("usernames",
                resultDTO.getContent().stream().filter(t -> !StringUtils.isEmpty(t.getMaintenanceUserId()))
                        .map(MaintenanceChangeDTO::getMaintenanceUserId)
                        .collect(Collectors.toList()).toArray(new String[1]));
        final ResultListDTO<Map<String, Object>> result = this.authMicroService.batchusers(usernames);
        if (result.isSuccess()) {
            final List<Map<String, Object>> data = result.getData();
            data.forEach(t -> {
                if (t.get("phone") != null) {
                    resultDTO.getContent().forEach(v -> {
                        if (t.get("username") != null) {
                            if (t.get("username").toString().equals(v.getMaintenanceUserId())) {
                                v.setMaintenancePhone(t.get("phone").toString());
                            }
                        }
                    });
                }
            });
        }
        return resultDTO;
    }

    /**
     * 更新资产
     *
     * @param model
     */
    @Override
    public MaintenanceChangeDTO changeAssetMaintenanceInfo(final MaintenanceChangeDTO dto) {

        MaintenanceChange model;
        try {
            model = this.changeRepository.getOne(dto.getId());

        } catch (final EntityNotFoundException e) {
            throw new UnitedException(ExceptionConstants.ENTITY_NOT_FOUND, new Object[] {dto.getId() });
        }

        if (dto.getChangeStatus().equals(MaintenanceChangeStatus.confirmed.getCode())) {
            if ((dto.getAssets() != null) && !dto.getAssets().isEmpty()) {
                dto.getAssets().forEach(asset -> {
                    if (dto.getManufacturerId() != null) {
                        asset.setManufacturerId(dto.getManufacturerId());
                    }
                    if (null != dto.getMaintenanceStart()) {
                        asset.setMaintenanceStart(dto.getMaintenanceStart());
                    }
                    if (null != dto.getMaintenanceEnd()) {
                        asset.setMaintenanceEnd(dto.getMaintenanceEnd());
                    }
                    if (!StringUtils.isEmpty(dto.getMaintenanceNote())) {
                        asset.setMaintenanceNote(dto.getMaintenanceNote());
                    }
                    if (null != dto.getMaintenanceUserId()) {
                        asset.setMaintenanceUserId(dto.getMaintenanceUserId());
                    }
                    if (!StringUtils.isEmpty(dto.getMaintenanceUserName())) {
                        asset.setMaintenanceUserName(dto.getMaintenanceUserName());
                    }

                    this.assetService.update(asset.getId(), asset);
                });
            }
        }

        dto.setId(model.getId());
        dto.setChangeStatus(MaintenanceChangeStatus.finish.getCode());
        model = this.changeConverter.toModel(dto);
        this.changeRepository.save(model);

        MaintenanceChangeServiceImpl.log.info("维保变更 -- 更新资产维保信息成功 id： " + dto.getId());
        return this.changeConverter.toDTO(model);
    }

}
